Vue 使用 Vue | 您所在的位置:网站首页 › socketio client 连接数据 › Vue 使用 Vue |
技术讨论群【522121825】 1. 上次的博客已经讲述了如何建立服务器,如何建立客户端,并且与服务器进行连接,那么本文接着上次,讲述一下客户端与服务器端的通讯是如何实现的。 PS:事件的发布与监听、广播事件、私聊事件、其他常用事件。 2. 事件的发布与监听: 2.1 emit()、on(): 在vue中,组件可以发布自定义事件,使用emit,其他地方直接使用 on 监听这个事件即可。而socket.io 也是类似的,发布事件用 emit ,监听事件用 on; // 监听客户端连接 io.on("connection", function (socket) { /* 每一个连接上来的用户,都会分配一个socket */ console.log("客户端有连接"); /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); }); // 给客户端发送消息(发布welcome事件) socket.emit("welcome", "欢迎连接socket"); /* socket实例对象会监听一个特殊函数,关闭连接的函数disconnect */ socket.on('disconnect', function () { console.log('用户关闭连接'); }); });例如上的代码,服务器端监听了‘connection’事件,(connection事件是socket的默认事件,指的是用户连接),还监听了login事件,发布了一个 welcome事件,监听一个disconnection事件,(disconnection也是默认事件,指的是用户断开连接) 2.2 发布与监听: 发布事件,就是我想给你发消息。监听事件,就是我想收到你的消息。就是一个 ‘发-收’ 的关系。(我自己的理解哈) 3. 客户端监听与发布: /* socket是监听服务器发布的自定义事件 */ sockets: { /* 监听welcome事件 */ welcome:function(data){ console.log("welcome data 数据返回 = >", data); }, },这个是监听服务器发布的事件,用sockets监听; methods: { /* 登录 */ login(){ console.log("login",this.username); /* 发送数据到服务器 */ this.$socket.emit('login',this.username); this.isLogin=true; this.msgList.push({type:'',msg:this.username+'登录成功'}); }, }这个是发布事件,定义在methods中,使用 this.$socket.emit(); 4. 启动服务器与Vue: 连接了两个客户端, 服务器输出连接消息; 5. 群聊事件 到此,已经简单讲述了事件的发布于监听,而socket.io的通讯就是建立在这个基础上。 我们使用vue-socket.io做聊天应用,无非就是私聊和群聊,下面慢慢来探究里面的技术; 5.1 普通群聊: socket.io 在群聊的处理上,是非常棒的!Introduction | Socket.IO 这个是socket.io 的官方文档,里面有更详细的描述。 我们还是先看一下服务器端的代码: var io = require("socket.io")(http, { allowEIO3: true, cors: { origin: "http://localhost:8080", methods: ["GET", "POST"], credentials: true } }); // 监听客户端连接 io.on("connection", function (socket) { /* 每一个连接上来的用户,都会分配一个socket */ console.log("客户端有连接"); /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); }); // 给客户端发送消息(发布welcome事件) socket.emit("welcome", "欢迎连接socket"); /* socket实例对象会监听一个特殊函数,关闭连接的函数disconnect */ socket.on('disconnect', function () { console.log('用户关闭连接'); }); });我先解释一下,这里面有两个非常重要的变量:io、socket; io是socket服务器对象(servers); socket是每一个连接上来的客户端实例; 所以群聊,就是给连接上来的所有人发送消息!而所有人存在io 服务器对象中,因此,广播事件: io.emit("hello", "world"); 5.2 socket.io 官方文档中,还有一点需要我们去注意的。 Rooms:A room is an arbitrary channel that sockets can join and leave. It can be used to broadcast events to a subset of clients: 我们可以加入房间或者离开房间,在广播事件的时候,就可以直接广播给该房间的客户端。 5.1我们说的是给连接上来的所有人,而现在这个是指定房间的客户端,还是有很大的区别的。 那么,我们如何定义房间,并给指定房间的客户端发送消息呢? // 在客户端连接的时候,指定加入某一个房间 io.on("connection", (socket) => { socket.join("some room"); }); // 给指定房间的客户端连接发送消息 io.to("some room").emit("some event");下面是房间的相关事件: 有兴趣的可以试试 以上便是群聊的相关方法。 5.2 私聊: 官方文档并没有过多的描述私聊的实现,只是给了一段示例代码: // to individual socketid (private message) io.to(socketId).emit(/* ... */);对于这个私聊,下面我说说我的理解。 6. socket.io 私聊实现方案: 6.1 新建数组实现 上述中的代码,我们只要找到你想私聊的客户端的socketid,调用这个API即可。但是连接上来的这么多客户端,我们是如何得知你想发送的对象的sockeid呢? 我们修改服务器端的代码如下: // 定义数组接收数据 var socketInfo=[]; /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); /* 将用户的id与socketid对应 */ socketInfo.push({ userid:data, socketid:socket.id }); console.log(socketInfo); });客户端: 服务器端: 这样一来,你想给谁发消息,只要在数组中遍历userid,取到这个socketid,即可实现。具体代码如下:(现在我是固定的 2 号,具体根据实际项目调整) 客户端: 不难理解,需要带一个用户id,来唯一识别你想给谁发消息。同时,还要监听服务器发送过来的数据: /* socket是监听服务器发布的自定义事件 */ sockets: { /* 监听私聊事件 */ chatPrivate:function(data){ console.log('有人找我私聊了',data); }, /* 监听welcome事件 */ welcome:function(data){ console.log("welcome data 数据返回 = >", data); }, },服务器端: /* 这里我们模拟 1 给 2 发消息 */ socket.on('1-2',data=>{ /* 遍历数组 */ socketInfo.forEach(s=>{ /* 判断该对象是不是我们需要发送的那个人 */ if(s.userid==data.userid){ /* 发送数据 */ io.to(s.socketid).emit('chatPrivate',data.msg); } }); });实现效果: 1号发送数据: 2号接收数据: 以上便是基于数组实现私聊,总结一下,就是要对应连接上来的用户ID,和连接的socketid,当我发起私聊的时候,能够找到对应用户的socketid即可!根本就是找到对方的socketid! 6.2 基于io服务器实例实现 io是socket服务器对象(servers); socket是每一个连接上来的客户端实例; 这次我们不用建立数组,用原始的方式实现。socket是连接实例,肯定是一个对象,因为我们取id,是通过socket.id实现的。所以我们可以在对象上追加一个属性:userid; 那么,大概会变成这样子: 原来的socket: socket:{ ... id:XXXXXXXXX ... } 加了自定义属性后: socket:{ ... id:XXXXXXXXX userid:XXXXXX ... } 这样,我们不就可以直接遍历存放socket的容器,找到userid,再取socketid不就实现了嘛??换句话说,连接上来的socket,应该是放在一个默认的数组中。这个默认的数组是什么?io? socket添加自定义属性: /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); /* 添加自定义属性 */ socket.userid=data; });下面是输出的io 感兴趣的小伙伴可以慢慢研究。 Server { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, ..... //此处省略 encoder: Encoder {}, _adapter: [class Adapter extends EventEmitter], sockets: Namespace { _events: [Object: null prototype] { connection: [Function (anonymous)] }, _eventsCount: 1, _maxListeners: undefined, sockets: Map(2) { 'R_pZZihjSjxrh8VaAAAA' => [Socket], 's2KCyEX2y0tBgDXhAAAC' => [Socket] }, _fns: [], _ids: 0, server: [Circular *1], name: '/', adapter: Adapter { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, nsp: [Circular *2], rooms: [Map], sids: [Map], encoder: Encoder {}, [Symbol(kCapture)]: false }, [Symbol(kCapture)]: false }, ........ //此处省略 }相信有感觉的已经找到了socket!没错,就是io.sockets.sockets。(一定要注意:io.sockets.sockets 是存放所有连接的用户实例的数组!!数组!!(Map(2))) 我简单说一下为什么是io.sockets.sockets: 理论上,应该是io.sockets就行了,第一个很好理解,io指的是Server,第二个sockets指的是命名空间,因为同一个服务器,可以根据不同的namespace分配不同的用户连接。这个请详细看官网说明,这里不再深入研究。 涉及了一个命名空间,所以才是io.sockets.sockets 那么,有了这个数据,我们就遍历这个,找到对应userid和socketid,不就能实现了嘛? /* 定义变量接收这个数组:一般我简写 scs */ var SocketConnections=io.sockets.sockets; console.log("客户端有连接"); /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); /* 添加自定义属性 */ socket.userid=data; }); /* 这里我们模拟 1 给 2 发消息 */ socket.on('1-2',data=>{ /* 遍历数组 */ SocketConnections.forEach(s=>{ /* 判断该对象是不是我们需要发送的那个人 */ if(s.userid==data.userid){ /* 发送数据 */ io.to(s.id).emit('chatPrivate',data.msg); } }); });注意:这里循环找的是id,不是socketid,socketid是我们自己定义的数组写的变量,而我们通过io.sockets.sockets找到的是socket本身,id就是他的属性!!! 以上就是 io 原生方式找到对应的连接实例。 7. 总结: 7.1 emit 发布事件 7.2 on 监听事件 7.3 io.emit() 群聊 [ 所有连接服务器的实例都会接收到消息 ] 7.4 Rooms:io.to('room name').emit() [ 在某房间里的用户能接收到数据 ] 7.5 私聊实现1:自定义数据,存放连接的唯一标识和socketid 7.6 私聊实现2:io.sockets.sockets,默认的服务器实例对象数组 7.7 私聊代码:io.to().emit() 7.8 socket.io事件速查表 以上是我的理解,可能有些错误或者不准确,欢迎留言指正。 想要源码,欢迎留言 ,后续会更新基于vuex管理的socket.io的使用。 |
CopyRight 2018-2019 实验室设备网 版权所有 |